package xin.mashibo.wanjiobutest.service;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Parcelable;
import android.util.Log;

import com.wanji.etcble.bean.CardConsumeRecord;
import com.wanji.etcble.bean.CardInformation;
import com.wanji.etcble.bean.CardOwner;
import com.wanji.etcble.bean.DeviceInformation;
import com.wanji.etcble.bean.LoadInitCreditBean;
import com.wanji.etcble.bean.ServiceStatus;
import com.wanji.etcble.bean.WJStructBean;
import com.wanji.etcble.service.WJBleAPI;

import java.util.ArrayList;
import java.util.List;

import xin.mashibo.wanjiobutest.activity.CardInfoActivity;
import xin.mashibo.wanjiobutest.vo.CardConsumeExtend;
import xin.mashibo.wanjiobutest.vo.CardOwnerExtend;
import xin.mashibo.wanjiobutest.vo.CardTransaction;
import xin.mashibo.wanjiobutest.vo.DeviceInfo;
import xin.mashibo.wanjiobutest.vo.LoadInitCreditExtend;

import static xin.mashibo.wanjiobutest.constant.ServiceConstant.CARDOWNER_KEY;
import static xin.mashibo.wanjiobutest.constant.ServiceConstant.CONSUME_LIST_KEY;
import static xin.mashibo.wanjiobutest.constant.ServiceConstant.DEVICE_INFO_KEY;
import static xin.mashibo.wanjiobutest.constant.ServiceConstant.KEYINDEX;
import static xin.mashibo.wanjiobutest.constant.ServiceConstant.MAC1_KEY;
import static xin.mashibo.wanjiobutest.constant.ServiceConstant.MSG_CONNECT;
import static xin.mashibo.wanjiobutest.constant.ServiceConstant.MSG_DISCONNECT;
import static xin.mashibo.wanjiobutest.constant.ServiceConstant.MSG_MAC1;
import static xin.mashibo.wanjiobutest.constant.ServiceConstant.MSG_MAC2;
import static xin.mashibo.wanjiobutest.constant.ServiceConstant.MSG_READCARD;
import static xin.mashibo.wanjiobutest.constant.ServiceConstant.MSG_READCONSUME;
import static xin.mashibo.wanjiobutest.constant.ServiceConstant.MSG_READDEVICE;
import static xin.mashibo.wanjiobutest.constant.ServiceConstant.MSG_READOWNER;
import static xin.mashibo.wanjiobutest.constant.ServiceConstant.MSG_TRANSACTION;
import static xin.mashibo.wanjiobutest.constant.ServiceConstant.NONE_READCARD;
import static xin.mashibo.wanjiobutest.constant.ServiceConstant.PING_10;
import static xin.mashibo.wanjiobutest.constant.ServiceConstant.PING_40;
import static xin.mashibo.wanjiobutest.constant.ServiceConstant.PROCTYPE;
import static xin.mashibo.wanjiobutest.constant.ServiceConstant.TERMINALNO;
import static xin.mashibo.wanjiobutest.constant.ServiceConstant.TRANSACTION_KEY;
import static xin.mashibo.wanjiobutest.constant.ServiceConstant.VERSION_40;


/**
 * 蓝牙OBU操作服务
 *
 * @author MaShibo
 *         on 2018/3/20
 */
public class ObuOptService {

    private static final String TAG = "ObuOptService";

    private WJBleAPI wjBleAPI;

    private Handler handler;

    private CardInformation cardInfo;


    public ObuOptService(WJBleAPI wjBleAPI, Handler handler) {
        this.wjBleAPI = wjBleAPI;
        this.handler = handler;
    }

    public void connect() {
        new Thread() {
            @Override
            public void run() {
                ServiceStatus status = wjBleAPI.connectDevice();
                Message msg = new Message();
                msg.what = MSG_CONNECT;
                msg.obj = status;
                handler.sendMessage(msg);
            }
        }.start();
    }

    public void disConnect() {
        new Thread() {
            @Override
            public void run() {
                ServiceStatus status = wjBleAPI.disconnectDevice();
                Message msg = new Message();
                msg.what = MSG_DISCONNECT;
                msg.obj = status;
                handler.sendMessage(msg);
            }
        }.start();
    }

    public void readCard() {
        new Thread() {
            @Override
            public void run() {
                CardInformation cardInfo = new CardInformation();
                ServiceStatus status = wjBleAPI.getCardInfo(cardInfo);
                Message msg = new Message();
                msg.what = MSG_READCARD;
                msg.obj = status;
                Bundle bundle = new Bundle();
                bundle.putParcelable(CardInfoActivity.CARD_INFO_BUNDLE, cardInfo);
                msg.setData(bundle);
                ObuOptService.this.cardInfo = cardInfo;
                handler.sendMessage(msg);
            }
        }.start();
    }

    public void readCardOwner() {
        new Thread() {
            @Override
            public void run() {
                CardOwner cardOwner = new CardOwner();
                ServiceStatus status = wjBleAPI.readCardOwnerRecord(cardOwner);
                Message msg = new Message();
                msg.what = MSG_READOWNER;
                msg.obj = status;
                Bundle bundle = new Bundle();
                bundle.putParcelable(CARDOWNER_KEY, new CardOwnerExtend(cardOwner));
                msg.setData(bundle);
                handler.sendMessage(msg);
            }
        }.start();
    }

    public void readConsume() {
        new Thread() {
            @Override
            public void run() {
                List<CardConsumeRecord> consumeList = new ArrayList<>();
                ServiceStatus status = wjBleAPI.readCardConsumeRecord(1, consumeList);
                Message msg = new Message();
                msg.what = MSG_READCONSUME;
                msg.obj = status;
                if (consumeList.size() > 0) {
                    Bundle bundle = new Bundle();
                    bundle.putParcelableArrayList(CONSUME_LIST_KEY, convertConsumeList(consumeList));
                    msg.setData(bundle);
                }
                handler.sendMessage(msg);
            }
        }.start();
    }

    public void readDevice() {
        new Thread() {
            @Override
            public void run() {
                DeviceInformation deviceInfo = new DeviceInformation();
                ServiceStatus status = wjBleAPI.getDeviceInformation(deviceInfo);
                Message msg = new Message();
                msg.what = MSG_READDEVICE;
                msg.obj = status;
                Bundle bundle = new Bundle();
                bundle.putParcelable(DEVICE_INFO_KEY, convertDeviceInfo(deviceInfo));
                msg.setData(bundle);
                handler.sendMessage(msg);
            }
        }.start();
    }

    public void readTransaction() {
        new Thread() {
            @Override
            public void run() {
                Message msg = new Message();
                msg.what = MSG_TRANSACTION;
                ServiceStatus status = new ServiceStatus();
                if (cardInfo == null) {
                    status.setServiceCode(NONE_READCARD);
                } else {
                    List<WJStructBean.CardTransactionRecord> cardRecordList = new ArrayList<>();
                    status = wjBleAPI.readCardTransactionRecord(VERSION_40.equals(cardInfo.getCardVersion()) ? PING_40 : PING_10, 20, cardRecordList);
                    Bundle bundle = new Bundle();
                    bundle.putParcelableArrayList(TRANSACTION_KEY, convertTransaction(cardRecordList));
                    msg.setData(bundle);
                    cardInfo = null;
                }
                msg.obj = status;
                handler.sendMessage(msg);
            }
        }.start();
    }

    public void readMac1(final int credit) {
        new Thread() {
            @Override
            public void run() {
                Message msg = new Message();
                msg.what = MSG_MAC1;
                ServiceStatus status = new ServiceStatus();
                if (cardInfo == null) {
                    status.setServiceCode(NONE_READCARD);
                } else {
                    LoadInitCreditBean creditBean = new LoadInitCreditBean();
                    status = wjBleAPI.loadCreditGetMac1(cardInfo.getCardId(), credit,
                            TERMINALNO, VERSION_40.equals(cardInfo.getCardVersion()) ? PING_40 : PING_10, PROCTYPE, KEYINDEX, creditBean);
                    if (creditBean != null) {
                        Log.d(TAG, "run: " + creditBean);
                        Bundle bundle = new Bundle();
                        bundle.putParcelable(MAC1_KEY, new LoadInitCreditExtend(creditBean));
                        msg.setData(bundle);
                    }
                    cardInfo = null;
                }
                msg.obj = status;
                handler.sendMessage(msg);
            }
        }.start();
    }

    public void writeCard(final String mac2) {
        new Thread() {
            @Override
            public void run() {
                ServiceStatus status = wjBleAPI.loadCreditWriteCard(mac2);
                Message msg = new Message();
                msg.what = MSG_MAC2;
                msg.obj = status;
                handler.sendMessage(msg);
            }
        }.start();
    }

    /**
     * 转换消费记录列表格式
     *
     * @param consumeList 消费记录列表
     * @return 消费记录列表
     */
    private ArrayList<? extends Parcelable> convertConsumeList(List<CardConsumeRecord> consumeList) {
        ArrayList<CardConsumeExtend> extendList = new ArrayList<>(consumeList.size());
        for (CardConsumeRecord cardConsumeRecord : consumeList) {
            extendList.add(new CardConsumeExtend(cardConsumeRecord));
        }
        return extendList;
    }

    /**
     * 转换设备信息格式
     *
     * @param deviceInformation 设备信息
     * @return 设备信息
     */
    private DeviceInfo convertDeviceInfo(DeviceInformation deviceInformation) {
        DeviceInfo deviceInfo = new DeviceInfo();
        deviceInfo.setBattery(deviceInformation.getBattery());
        deviceInfo.setDevAddress(deviceInformation.getDevAddress());
        deviceInfo.setDevName(deviceInformation.getDevName());
        deviceInfo.setErrorCode(deviceInformation.getErrorCode());
        deviceInfo.setSn(deviceInformation.getSn());
        deviceInfo.setVerId(deviceInformation.getVerId());
        deviceInfo.setVersion(deviceInformation.getVersion());
        return deviceInfo;
    }

    /**
     * 转换交易记录信息
     *
     * @param records 交易记录
     * @return 交易记录
     */
    private ArrayList<? extends Parcelable> convertTransaction(List<WJStructBean.CardTransactionRecord> records) {
        ArrayList<CardTransaction> transactions = new ArrayList<>(records.size());
        for (WJStructBean.CardTransactionRecord record : records) {
            transactions.add(new CardTransaction(record));
        }
        return transactions;
    }

}
